package com.xy.smartsms.plugincmcc;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.LruCache;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.xy.smartsms.data.BaseSmsPlugin;
import com.xy.smartsms.data.ISmsPlugin;
import com.xy.smartsms.data.PublicInfoData;
import com.xy.smartsms.data.SmsItem;
import com.xy.smartsms.util.Log;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import cn.cmcc.online.smsapi.MenuClickHelper;
import cn.cmcc.online.smsapi.SmsPlus;
import cn.cmcc.online.smsapi.Terminal;

public class CMCCSmsPlugin extends BaseSmsPlugin {
    private static final String TAG = CMCCSmsPlugin.class.getSimpleName();
    private static final String PUBLICINFO_NAME = "name";
    private static final String PUBLICINFO_LOGO = "logo";
    private static final String PUBLICINFO_MENU = "menu";
    private static final String SUB_MENU = "Submenu";
    private static final String ACTION_TYPE = "Opentype";
    private static final String ACTION_URL = "Openurl";
    private static final String MENU_NAME = "Menuname";

    private CMCCDataCache mDataCache = null;
    private int mParseTimeout = 6000;
    private static final LruCache<String, PublicInfoData> sPublicInfoCache = new LruCache<>(100);

    public CMCCSmsPlugin(Context context) {
        super(context);

        mDataCache = CMCCDataCache.getInstance(mContext);
    }

    public void finalize() throws Throwable {

    }

    @Override
    public void init(Object doAction, Map<String, String> extend) {
        super.init(doAction, extend);
        mParams.put("custom_plugin_type", "view");
        if (extend != null) {
            String timeout = extend.get("custom_parse_time_out");
            if (!TextUtils.isEmpty(timeout)) {
                mParseTimeout = Integer.parseInt(timeout);
            }
        }

        SmsPlus.init(mContext);
    }

    private void startActivity(Context context, String url) {
        if (TextUtils.isEmpty(url) || context == null) {
            return;
        }

        try {
            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addCategory(Intent.CATEGORY_BROWSABLE);
            mContext.startActivity(intent);
        } catch (Throwable t) {
            Log.e(TAG, "startActivity", t);
        }
    }

    private void parseCardAsync(final int type, final SmsItem item, final ISmsPluginCallback callback) {
        if (item.isScrolling() || !isNetworkAllowed()) {
            cardCallback(callback, ISmsPlugin.STATUS_SUCCESS, type, null);
            return;
        }

        // in order to update ui on time
        cardCallback(callback, ISmsPlugin.STATUS_FAIL, type, null);
        getCardPool().execute(new Runnable() {
            public void run() {
                String cachedResult = mDataCache.queryCacheResultFromDB(item);
                if (cachedResult != null) {
                    cardCallback(callback, ISmsPlugin.STATUS_SUCCESS, type, null);
                    return;
                }

                final Terminal.TerminalCallBack pluginCallback = new Terminal.TerminalCallBack() {
                    @Override
                    public void loadCard(final WebView webView, boolean val) {
                        if (webView != null) {
                            webView.setWebViewClient(new WebViewClient() {

                                @Override
                                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                                    startActivity(mContext, url);
                                    return true;
                                }
                            });
                        }

                        JSONObject resultObj = buildData(webView);
                        if (resultObj == null) {
                            // only record the empty result in order to improve performance
                            mDataCache.updateCacheData(item, true);
                        }

                        cardCallback(callback, ISmsPlugin.STATUS_SUCCESS, type, resultObj);
                    }

                    @Override
                    public void loadUrl(Context context, String url) {
                        startActivity(context, url);
                    }
                };

                try {
                    Terminal.getCardView(mContext,
                            item.getPhone(),
                            item.getBody(),
                            "",
                            pluginCallback);
                } catch (Throwable t) {
                    Log.e(TAG, "", t);
                }
            }
        });
    }

    private JSONObject buildData(WebView webView) {
        JSONObject obj = null;
        if (webView == null) {
            return obj;
        }

        try {
            obj = new JSONObject().put("carrier_view", webView);
        } catch (Throwable t) {
            Log.e(TAG, "", t);
        }

        return obj;
    }

    @Override
    public void parseCard(final int type, final SmsItem item, final ISmsPluginCallback callback) {
        if (type == ISmsPlugin.TYPE_RICH) {
            String cachedResult = mDataCache.queryCacheResult(item);
            if (cachedResult != null) {
                cardCallback(callback, ISmsPlugin.STATUS_SUCCESS, ISmsPlugin.TYPE_RICH, null);
                return;
            }

            parseCardAsync(type, item, callback);
        } else {
            cardCallback(callback, ISmsPlugin.STATUS_FAIL, type, null);
        }
    }

    private String handleCMCCMenuData(String infoString) {
        if (infoString == null) {
            return null;
        }

        try {
            infoString = infoString.replace("\"Menuname\"", "\"name\"").replace("\"Submenu\"", "\"secondmenu\"");
            JSONObject infoJson = new JSONObject(infoString);
            JSONArray array = infoJson.optJSONArray(PUBLICINFO_MENU);
            if (array == null || array.length() <= 0) {
                return null;
            }

            return array.toString();
        } catch (Throwable t) {
            Log.e(TAG, "handleCMCCMenuData", t);
        }

        return null;
    }

    private PublicInfoCallable getPublicInfoCallable() {
        // avoid pending menu request
        return new PublicInfoCallable(mContext);
    }

    private void parsePublicInfoAsync(final String phone, final ISmsPluginCallback callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                PublicInfoCallable callable = getPublicInfoCallable();
                callable.setPhone(phone);
                String infoString = callable.executeWithTimeout(mParseTimeout);
                PublicInfoData data = new PublicInfoData();
                data.manufacture = "CMCC";
                data.json = handleCMCCMenuData(infoString);
                if (TextUtils.isEmpty(infoString)) {
                    publicInfoCallback(callback, ISmsPlugin.STATUS_FAIL, data);
                    return;
                }

                List<PublicInfoData.MenuItem> menuItemList = new ArrayList<PublicInfoData.MenuItem>();
                try {
                    JSONObject infoJson = new JSONObject(infoString);
                    data.name = infoJson.optString(PUBLICINFO_NAME);
                    data.logo = infoJson.optString(PUBLICINFO_LOGO);
                    JSONArray array = infoJson.optJSONArray(PUBLICINFO_MENU);
                    if (array == null || array.length() <= 0) {
                        publicInfoCallback(callback, ISmsPlugin.STATUS_SUCCESS, data);
                        return;
                    }

                    for (int menuIndex = 0; menuIndex < array.length(); menuIndex++) {
                        JSONObject menuObj = array.getJSONObject(menuIndex);
                        PublicInfoData.MenuItem menuItem = new PublicInfoData.MenuItem();
                        menuItem.name = menuObj.optString(MENU_NAME);

                        JSONArray subArray = menuObj.optJSONArray(SUB_MENU);
                        if (subArray != null && subArray.length() > 0) {
                            List<PublicInfoData.SubMenuItem> subMenuItemList = new ArrayList<PublicInfoData.SubMenuItem>();
                            for (int subMenuIndex = 0; subMenuIndex < subArray.length(); subMenuIndex++) {
                                PublicInfoData.SubMenuItem subMenuItem = new PublicInfoData.SubMenuItem();
                                JSONObject subMenuObj = subArray.getJSONObject(subMenuIndex);
                                subMenuItem.name = subMenuObj.optString(MENU_NAME);
                                subMenuItem.json = new JSONObject(subMenuObj,
                                        new String[]{MENU_NAME, ACTION_TYPE, ACTION_URL}).put("ManufactureData", "CMCC");

                                subMenuItemList.add(subMenuItem);
                            }

                            menuItem.subMenuList = subMenuItemList;
                        } else {
                            menuItem.json = new JSONObject(menuObj, new String[]{MENU_NAME, ACTION_TYPE, ACTION_URL})
                                    .put("ManufactureData", "CMCC");
                        }

                        menuItemList.add(menuItem);
                    }

                    data.menuList = menuItemList;
                    sPublicInfoCache.put(phone, data);
                    publicInfoCallback(callback, ISmsPlugin.STATUS_SUCCESS, data);
                    return;
                } catch (Throwable t) {
                    Log.e(TAG, "", t);
                }
            }
        }).start();
    }

    @Override
    public void parsePublicInfo(String phone, Map<String, String> extend, ISmsPluginCallback callback) {
        PublicInfoData data = sPublicInfoCache.get(phone);
        if (data != null) {
            Log.v(TAG, "parsePublicInfo: cache hit:" + data);
            publicInfoCallback(callback, ISmsPlugin.STATUS_SUCCESS, data);
            callback = null; // update anyway
        }

        if (!isNetworkAllowed()) {
            Log.i(TAG, "parsePublicInfo: network problem");
            publicInfoCallback(callback, ISmsPlugin.STATUS_SUCCESS, null);
            return;
        }

        parsePublicInfoAsync(phone, callback);
    }

    @Override
    public void processAction(Activity activity, String action, Map<String, String> extend) {
        try {
            JSONObject json = new JSONObject(action);
            String phone = extend.get("phoneNum");
            MenuClickHelper.menuJump(mContext,
                    phone,
                    json.optString(MENU_NAME),
                    json.optString(ACTION_TYPE),
                    json.optString(ACTION_URL));
        } catch (Throwable t) {
            Log.e(TAG, "processAction", t);
        }
    }

    @Override
    public void loadCache(String phone) {
        if (!TextUtils.isEmpty(phone)) {
            CMCCDataCache.getInstance().loadCacheResultsFromDB(phone);
        }
    }

    @Override
    public void clearCache(String phone) {
        CMCCDataCache.getInstance().clearLruCache();
    }
}